<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>10Vue监测数据变化总结</title>
  <script src="../js/vue.js"></script>
</head>
<body>
  <div id="app">
    <h1>{{title}}</h1>
    <h3>学生信息</h3>
    <button @click="student.age++">age++</button>
    <button @click="addGender">addGender</button>
    <button @click="changeGender">changeGender</button>
    <button @click="addFriend">addFriend</button>
    <button @click="changeFirstFriendName">change frist friend name</button>
    <button @click="addHobby">addHobby</button>
    <button @click="changeFirstHobby">changeFirstHobby</button>
    <button @click="filterRun">filterRun</button>
    <h5>name:{{student.name}}</h5>
    <h5>age:{{student.age}}</h5>
    <h5 v-if="student.gender">gender:{{student.gender}}</h5>
    <h5>hobby</h5>
    <ul>
      <li v-for="(h, index) in student.hobby" :key="index">{{h}}</li>
    </ul>
    <h5>friends</h5>
    <ul>
      <li v-for="f in student.friends" :key="f.age">{{f.name}}-{{f.age}}</li>
    </ul>
  </div>
  <script>
    /* 
      Vue监测数据变化的原理：
        1 Vue会监测data中所有层次的数据

        2 Vue如何监测对象中的数据？
          通过setter事件监测，在初始化vm示例时就要将数据放到data中
          通过this.car.price方式后续添加到data中的数据，Vue默认不做响应式处理
          需要通过set(target, name, value)实现响应式

        3 Vue如何监测数组中的数据？
          通过包裹数组更新元素的方法实现，其本质就是：调用数组的原生方法对数组进行更新，重新解析模板更新页面

        4 在Vue修改数组中某个元素需要用如下被包裹的API实现：
          push，pop，shift，unshift，reverse，splice，sort
          Vue.set()
          注：对于其他不改变原数组本身的原生方法，例如filter等，我们可以将filter后的新数组直接覆盖data中的老数组即可。

        5 set方法中，target不能是vm，也不能是根数据data(vm_data)
    */
    new Vue({
      el: '#app',
      data(){
        return {
          title: 'Vue监测数据变化总结',
          student: {
            name: 'tom',
            age: 18,
            hobby: ['run', 'race', 'jump'],
            friends: [
              {
                name: 'cat',
                age: 1
              },
              {
                name: 'dog',
                age: 2
              }
            ]
          }
        }
      },
      methods: {
        addGender() {
          // Vue.set(this.student, 'gender', '男')
          this.$set(this.student, 'gender', '男')
        },
        changeGender() {
          this.student.gender = '女'
        },
        addFriend() {
          this.student.friends.unshift({
            name: 'pig',
            age: 3
          })
        },
        changeFirstFriendName() {
          this.student.friends[0].name = 'zhangsan'
        },
        addHobby() {
          this.student.hobby.push('rush')
        },
        changeFirstHobby() {
          // this.student.hobby.splice(0, 1, 'swim')
          // Vue.set(this.student.hobby, 0, 'swim')
          this.$set(this.student.hobby, 0, 'swim')
        },
        filterRun() {
          this.student.hobby = this.student.hobby.filter(h => h !== 'run')
        }
      }
    })
  </script>
</body>
</html>